/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package model;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

/**
 *
 * @author Anderson
 */
public class SintaticalAnalyser {

    private List<Token> listadeTokens;
    //  private List<Token> listadePalavrasReservadas;
    private int indiceToken = 0;
    private int noprograma = 0;
    private int noidentificador = 0;
    private int noabrechave = 0;
    private int nofechaChave = 0;
    private int noPontoeVirgula = 0;
    private Token tokenaux;

    public SintaticalAnalyser(List<Token> lista) {
        listadeTokens = lista;
        Token cifrão = new Token("$", 0, "fim de analise sitática");
        listadeTokens.add(cifrão);
        imprimeListaToken();
        // analyseListTokens();
        // this.imprimeListaToken();
    }

    public void estrutura(Token token) {
        tokenaux = token;
        // System.out.println("" + token.getToken());
        if (tokenaux.getTipo().equals("Palavra Reservada")) {
            System.out.println("passou e era Palavra Reservada");
            //constantes(tokenaux);

        } else if (tokenaux.getTipo().equals(";")) {
            System.out.println("passou e era o ';'");
            tokenaux = proximoToken();
        }
        noidentificador = 0;
        constantes(tokenaux);
        noPontoeVirgula = 0;
        noabrechave = 0;
        nofechaChave = 0;
        noidentificador = 0;
        variaveis(tokenaux);
        registro();
        noidentificador = 0;
        noPontoeVirgula = 0;
        renomearTipo();
        funcao();
    }

    public void funcao() {
        if (tokenaux.getToken().equals("funcao")) {
            System.out.println("Bloco Funcao declarado");
            tokenaux = proximoToken();
            corpo();

        } else {
            System.out.println("Bloco de Funcao não declarado");
            while (!tokenaux.getToken().equals("principal")) {
                tokenaux = proximoToken();
            }
        }
    }

    public void corpo() {
        Token tokenteste = tokenaux;
        tipoFuncao(tokenaux);

        if (tokenteste.equals(tokenaux)) {
            if(tokenaux.getToken().equals("principal")){
                System.out.println("principal encontrado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: Esperado 'principal'");
            }
            funcaoCorpoPrincipal();
        } else {
            indiceToken--;                     //foi pra tipos funções
            tokenaux = tokenteste;

            tipoFuncao(tokenaux);
            if(tokenaux.getTipo().equals("Identificador")){
                System.out.println("Identificador encontrado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: Identificador esperado");
            }
            listaParametros();
            funcaoCorpo();
            funcao();
        }

    }

    public void listaParametros(){
        if(tokenaux.getToken().equals("(")){
            System.out.println("( encontrado!");
            tokenaux = proximoToken();
        }else{
            System.out.println("ERRO: ( era esperado");
        }
        parametroFuncao();
    }

    public void parametroFuncao(){
        Token tokenteste = tokenaux;
        tipo(tokenaux);

        if (tokenteste.equals(tokenaux)) {
            if(tokenaux.getToken().equals(")"))  {  // foi ')'
                System.out.println(") encontrado");
                tokenaux = proximoToken();

            }else{
                System.out.println("ERRO: ) esperado");
            }
        }else{
            indiceToken--;
            tokenaux = tokenteste;
            tipoParametros();
        }
    }

    public void tipoParametros(){
        tipo(tokenaux);
        if(tokenaux.getTipo().equals("Identificador")){
            System.out.println("Identificador encontrado");
            tokenaux = proximoToken();
        }else{
            System.out.println("ERRO: Identificador esperado");
        }
        tipoNomeFatorado();

    }

    public void tipoNomeFatorado(){
        if(tokenaux.getToken().equals(",")){
            System.out.println(", Encontrado");
            tokenaux = proximoToken();
            tipoParametros();
        }else{
          // System.out.println("ERRO: esperado o ','");

            Token tokenteste = tokenaux;
            tipo(tokenaux);

            if (tokenteste.equals(tokenaux)) {

                if (tokenaux.getToken().equals(")")) {
                    System.out.println(") Encontrado");
                    tokenaux = proximoToken();
                } else {
                    System.out.println("ERRO: ) não encontrado");
                }
            }else{
                System.out.println("ERRO: esperado o ','");
                indiceToken--;
                tokenaux = tokenteste;
                tipoParametros();
            }

        }



    }

    public void funcaoCorpo(){
        if(tokenaux.getToken().equals("{")){
            System.out.println("'{' Encontrado");
            tokenaux = proximoToken();
        }else{
             System.out.println("ERRO: { não encontrado");
        }
        variaveis(tokenaux);
        comandos();
        retorno();

        if(tokenaux.getToken().equals("}")){
            System.out.println("'}' Encontrado");
            tokenaux = proximoToken();
        }else{
             System.out.println("ERRO: } não encontrado");
        }
    }

    

    public void comandos(){

        if(tokenaux.getToken().equals("se") || tokenaux.getToken().equals("para") || tokenaux.getToken().equals("enquanto") || tokenaux.getToken().equals("leia") || tokenaux.getToken().equals("escreva") || tokenaux.getTipo().equals("Identificador")){
            opcoesComandos();
            comandos();
        }else{
            System.out.println("Bloco 'comandos' não inicializado");
        }
    }

    public void opcoesComandos(){
        if(tokenaux.getToken().equals("se")){
            System.out.println("Palavra 'se' Identificada");
            tokenaux = proximoToken();
            if(tokenaux.getToken().equals("(")){
                System.out.println("'(' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: '(' não identificado");
            }
            expressao();
            if(tokenaux.getToken().equals(")")){
                System.out.println("')' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: ')' não identificado");
            }
            if(tokenaux.getToken().equals("{")){
                System.out.println("'{' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: '{' não identificado");
            }
            comandos();
            if(tokenaux.getToken().equals("}")){
                System.out.println("'}' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: '}' não identificado");
            }
            senao();

        }else{
            System.out.println("Palavra 'se' não Encontrada");
        }


        if(tokenaux.getToken().equals("para")){
            System.out.println("Palavra 'para' Identificada");
            tokenaux = proximoToken();

            if(tokenaux.getToken().equals("(")){
                System.out.println("'(' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: '(' não identificado");
            }

            atribuicoes();

            if(tokenaux.getToken().equals(";")){
                System.out.println(" ';' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: ';' não identificado");
            }

            expressaoLogica();

            if(tokenaux.getToken().equals(";")){
                System.out.println(" ';' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: ';' não identificado");
            }

            atribuicoes();

            if(tokenaux.getToken().equals(")")){
                System.out.println("')' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: ')' não identificado");
            }


            if(tokenaux.getToken().equals("{")){
                System.out.println("'{' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: '{' não identificado");
            }

            comandos();


            if(tokenaux.getToken().equals("}")){
                System.out.println("'}' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: '}' não identificado");
            }


        }else{
            System.out.println("Palavra 'para' não Encontrada");
        }



        if(tokenaux.getToken().equals("enquanto")){
            System.out.println("Palavra 'enquanto' Identificada");
            tokenaux = proximoToken();

            if(tokenaux.getToken().equals("(")){
                System.out.println("'(' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: '(' não identificado");
            }

            condicaoEnquanto();

            if(tokenaux.getToken().equals(")")){
                System.out.println("')' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: ')' não identificado");
            }


            if(tokenaux.getToken().equals("{")){
                System.out.println("'{' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: '{' não identificado");
            }

            comandos();


            if(tokenaux.getToken().equals("}")){
                System.out.println("'}' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: '}' não identificado");
            }

        }else{
            System.out.println("Palavra 'enquanto' não Encontrada");
        }


        if(tokenaux.getToken().equals("leia")){
            System.out.println("Palavra 'leia' Identificada");
            tokenaux = proximoToken();

            if(tokenaux.getToken().equals("(")){
                System.out.println("'(' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: '(' não identificado");
            }

            fatorLeia();

            if(tokenaux.getToken().equals(";")){
                System.out.println(" ';' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: ';' não identificado");
            }

        }else{
            System.out.println("Palavra 'leia' não Encontrada");
        }



        if(tokenaux.getToken().equals("escreva")){
            System.out.println("Palavra 'escreva' Identificada");
            tokenaux = proximoToken();

            if(tokenaux.getToken().equals("(")){
                System.out.println("'(' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: '(' não identificado");
            }

            fatorEscrita();

            if(tokenaux.getToken().equals(";")){
                System.out.println(" ';' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: ';' não identificado");
            }

        }else{
            System.out.println("Palavra 'escreva' não Encontrada");
        }


        if(tokenaux.getTipo().equals("Identificador")){
            System.out.println("Palavra 'Identificador' Identificada");
            atribuicoes();
        }else{
            System.out.println("Palavra 'Identificador' não Encontrada");
        }
    }



    public void expressao(){

    }

    public void atribuicoes(){

    }

    public void expressaoLogica(){

    }

    public void condicaoEnquanto(){

    }

    public void matriz(){
        
    }

    public void senao(){
        if(tokenaux.getToken().equals("senao")){
            System.out.println("Palavra 'senao' Identificada");
            tokenaux = proximoToken();

            if(tokenaux.getToken().equals("{")){
                System.out.println("'{' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: '{' não identificado");
            }

            comandos();


            if(tokenaux.getToken().equals("}")){
                System.out.println("'}' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: '}' não identificado");
            }


        }else{
            System.out.println("Campo 'senao' não declarado");
        }
    }

    public void fatorLeia(){
        if(tokenaux.getTipo().equals("Identificador")){
            System.out.println("Identificador encontrado");
            tokenaux = proximoToken();
            auxLeia();
        }else{
            System.out.println("Identificador não encontrado Fator Leia não iniciado");
        }

    }

    public void auxLeia(){
        if(tokenaux.getToken().equals(",")){
                System.out.println("',' Identificado");
                tokenaux = proximoToken();
                fatorLeia();
        }else{
                if(tokenaux.getToken().equals(")")){
                System.out.println("')' Identificado");
                tokenaux = proximoToken();
                }else{
                System.out.println("ERRO: ')' e nem ',' não identificados");
                }
        }
    }

    public void fatorEscrita(){

        fatorAux();
        auxEsc();
    }

    public void auxEsc(){

        if(tokenaux.getToken().equals(",")){
                System.out.println("',' Identificado");
                tokenaux = proximoToken();
                fatorEscrita();
        }else{
            if(tokenaux.getToken().equals(")")){
                System.out.println("')' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: ',' e ')' não identificados");
            }


        }
    }

    public void fatorAux(){
        if(tokenaux.getToken().equals("cadeia")){
                System.out.println("'cadeia' Identificado");
                tokenaux = proximoToken();
            }else{
                expressaoAritmetica();
            }
    }

    public void expressaoAritmetica(){
        termoAritm();
        proxTrechoExpAritm();
    }

    public void termoAritm(){
        fator();
        complementoFator();
    }

    public void fator(){
        if(tokenaux.getTipo().equals("Identificador")){
            System.out.println("Identificador encontrado");
            tokenaux = proximoToken();
            complementoReferenciaVariado();
        }else{
            if(tokenaux.getTipo().equals("Numero Inteiro") || tokenaux.getTipo().equals("Numero Decimal")){
               System.out.println("Numero encontrado");
                tokenaux = proximoToken();
            }else if(tokenaux.getToken().equals("(")){
                System.out.println("'(' encontrado");
                tokenaux = proximoToken();
                expressaoAritmetica();

            }else if(tokenaux.getToken().equals(")"))
                {
                    System.out.println("')' encontrado");
                    tokenaux = proximoToken();
                }
                else{
                System.out.println("ERRO: 'fator' mal formado");

            }
        }
    }

    public void complementoFator(){
        if(tokenaux.getToken().equals("*") || tokenaux.getTipo().equals("OPERADOR DE DIVISÃO")){
            operadorMultiplicacao();
            termoAritm();

        }else{
            System.out.println("Sem complemento fator");
        }

    }

    public void complementoReferenciaVariado(){
        if(tokenaux.getToken().equals("[")){
            System.out.println("'[' Identificado");
            tokenaux = proximoToken();
            expressaoAritmetica();
            if(tokenaux.getToken().equals("]")){
                 System.out.println("']' Identificado");
                tokenaux = proximoToken();
            }else{
                System.out.println("ERRO: ']' não Identificado");
            }
            matriz();

        }else{
           System.out.println("'[' não Identificado");
           if(tokenaux.getToken().equals(".")){
                 System.out.println("'.' Identificado");
                tokenaux = proximoToken();

                if(tokenaux.getTipo().equals("Identificador")){
                 System.out.println("'Identificador' Identificado");
                tokenaux = proximoToken();
                }else{
                System.out.println("ERRO: 'Identificador' não Encontrado");
                }

            }else{
                System.out.println("'.' não Identificado");
            }

        }
    }

    public void operadorMultiplicacao(){
        if(tokenaux.getToken().equals("*")){
            System.out.println("Operador '*' encontrado");
            tokenaux = proximoToken();
        }else if(tokenaux.getTipo().equals("OPERADOR DE DIVISÃO")){
            System.out.println("Operador '/' encontrado");
            tokenaux = proximoToken();
        }else{
            System.out.println("ERROR: Operador '*' e nem operador '/' encontrados");
        }
    }

    public void proxTrechoExpAritm(){

        if(tokenaux.getToken().equals("+") || tokenaux.getToken().equals("-")){
            operadorSoma();
            expressaoAritmetica();
        }else{
            System.out.println("Operador soma não identificado");
        }
    }

    public void operadorSoma(){
        
    }

    public void retorno(){
        if(tokenaux.getToken().equals("retorno")){
            System.out.println("'retorno' Encontrado");
            tokenaux = proximoToken();
        }else{
             System.out.println("ERRO: retorno não encontrado");
        }

        valor();

        if(tokenaux.getToken().equals(";")){
            System.out.println("Palavra ';' identificada");
            tokenaux = proximoToken();
        }else{
            System.out.println("ERROR: Esperado o ';'");
        }

    }

   
    public void valor(){
        if(tokenaux.getToken().equals("vazio") || tokenaux.getTipo().equals("Identificador")){
            System.out.println("valor identificado corretamente");
            tokenaux = proximoToken();

        }else{
            System.out.println("ERRO: Valor de retorno inválido!");
        }
    }

    public void funcaoCorpoPrincipal(){
        if(tokenaux.getToken().equals("{")){
            System.out.println("'{' Encontrado");
            tokenaux = proximoToken();
        }else{
             System.out.println("ERRO: { não encontrado");
        }
        variaveis();
        comandos();

        if(tokenaux.getToken().equals("retorno")){
            System.out.println("'retorno' Encontrado");
            tokenaux = proximoToken();
        }else{
             System.out.println("ERRO: retorno não encontrado");
        }

        if(tokenaux.getToken().equals("vazio")){
            System.out.println("'vazio' Encontrado");
            tokenaux = proximoToken();
        }else{
             System.out.println("ERRO: vazio não encontrado");
        }

        if(tokenaux.getToken().equals(";")){
            System.out.println("Palavra ';' identificada");
            tokenaux = proximoToken();
        }else{
            System.out.println("ERROR: Esperado o ';'");
        }

        if(tokenaux.getToken().equals("}")){
            System.out.println("'}' Encontrado");
            tokenaux = proximoToken();
        }else{
             System.out.println("ERRO: } não encontrado");
        }
    }

    public void renomearTipo() {

        if (tokenaux.getToken().equals("tipo") || noidentificador == 1) {

            if (noidentificador != 1) {
                System.out.println("Bloco de tipo declarado");
                tokenaux = proximoToken();
                tipo(tokenaux);
            }
            if (tokenaux.getTipo().equals("Identificador") || noidentificador == 1) {
                if (noidentificador != 1) {
                    System.out.println("Identificador encontrado");
                    tokenaux = proximoToken();
                }
                if (tokenaux.getToken().equals(";")) {
                    System.out.println("; encontrado");
                    tokenaux = proximoToken();

                } else {
                    System.out.println("ERRO:  Esperado o ';' ");
                    for (int i = indiceToken; i < listadeTokens.size(); i++) {

                        if (tokenaux.getToken().equals(";")) {
                            System.out.println("';' encontrado");
                            break;
                        } else if (tokenaux.getTipo().equals("Palavra Reservada")) {
                            System.out.println("';' esperado, mas encontrado Palavra Reservada");
                            break;
                        }
                        tokenaux = proximoToken();
                    }

                }
                noidentificador = 0;
                noPontoeVirgula = 0;
                renomearTipo();
            } else {
                System.out.println("ERRO: Identificador esperado");
                noidentificador = 1;
                renomearTipo();

            }
        } else {
            System.out.println("Bloco de tipo não declarado");
            while (!tokenaux.getToken().equals("funcao") && !tokenaux.getToken().equals("principal")) {
                tokenaux = proximoToken();
            }
        }
    }

    public void registro() {
        if (tokenaux.getToken().equals("registro") || noidentificador == 1 || noabrechave == 1) {
            if (noidentificador != 1) {
                if (noabrechave != 1) {
                    System.out.println("registro encontrado");
                    tokenaux = proximoToken();
                }

            }

            if (tokenaux.getTipo().equals("Identificador") || noidentificador == 1 || noabrechave == 1) {
                if (noidentificador != 1) {
                    if (noabrechave != 1) {
                        System.out.println("identificador encontrado");
                        tokenaux = proximoToken();
                    }

                }
                if (tokenaux.getToken().equals("{") || noabrechave == 1) {
                    if (noabrechave != 1) {
                        System.out.println("{ encontrado");
                        tokenaux = proximoToken();
                    }
                    noidentificador = 0;
                    noabrechave = 0;
                    declaracaoRegistro();
                    noidentificador = 0;
                    noabrechave = 0;
                    registro();

                } else {
                    System.out.println("ERRO: { esperado");
                    noabrechave = 1;
                    registro();
                }



            } else {
                System.out.println("ERRO: Identificador esperado");
                noidentificador = 1;
                registro();
            }



        } else {
            System.out.println("Bloco de registro não declarado");
            while (!tokenaux.getToken().equals("tipo") && !tokenaux.getToken().equals("funcao") && !tokenaux.getToken().equals("principal")) {
                tokenaux = proximoToken();
            }
        }
    }

    public void declaracaoRegistro() {
        if (noidentificador != 1) {
            tipo(tokenaux);
        }
        if (tokenaux.getTipo().equals("Identificador") || noidentificador == 1) {
            if (noidentificador != 1) {
                System.out.println("identificador encontrado");
                tokenaux = proximoToken();
            }
            if (tokenaux.getToken().equals(";") || noPontoeVirgula == 1) {
                if (noPontoeVirgula != 1) {
                    System.out.println("; encontrado");
                    tokenaux = proximoToken();
                }
                noidentificador = 0;
                noabrechave = 0;
                declaracaoRegistroVariaveis();


            } else {
                System.out.println("ERRO: ; esperado");
                noPontoeVirgula = 1;
                declaracaoRegistro();
            }



        } else {
            System.out.println("ERRO: Identificador esperado");
            noidentificador = 1;
            declaracaoRegistro();
        }

    }

    public void declaracaoRegistroVariaveis() {

        Token tokenteste;
        tokenteste = tokenaux;

        if (nofechaChave != 1) {
            tipo(tokenaux);
        }

        if (tokenteste.equals(tokenaux) || nofechaChave == 1) {

            if (tokenaux.getToken().equals("}") || nofechaChave == 1) {
                if (nofechaChave != 1) {
                    System.out.println("} encontrado");
                    tokenaux = proximoToken();
                }
                if (tokenaux.getToken().equals(";")) {
                    System.out.println("; encontrado");
                    tokenaux = proximoToken();
                } else {
                    System.out.println("ERRO:  Esperado o ';' ");
                    for (int i = indiceToken; i < listadeTokens.size(); i++) {

                        if (tokenaux.getToken().equals(";")) {
                            System.out.println("';' encontrado");
                            break;
                        } else if (tokenaux.getTipo().equals("Palavra Reservada")) {
                            System.out.println("';' esperado, mas encontrado Palavra Reservada");
                            break;
                        }
                        tokenaux = proximoToken();
                    }
                }
            } else {
                System.out.println("ERRO: } era esperado");
                nofechaChave = 1;
                declaracaoRegistroVariaveis();
            }
        } else {
            indiceToken--;
            tokenaux = tokenteste;
            declaracaoRegistro();
        }
    }

    public void declaracaoConstantesMesmoTipo(Token token) {

        tokenaux = token;
        if (tokenaux.getToken().equals(",")) {
            tokenaux = proximoToken();
            if (tokenaux.getTipo().equals("Identificador")) {
                tokenaux = proximoToken();
                if (tokenaux.getToken().equals("=")) {
                    tokenaux = proximoToken();
                    valorConstante(tokenaux);
                    declaracaoConstantesMesmoTipo(tokenaux);
                } else {
                    System.out.println("Operador '=' não encontrado. Valor não atribuido");
                    while (!tokenaux.getToken().equals(",") && !tokenaux.getToken().equals(";")
                            && !tokenaux.getToken().equals("}") && !tokenaux.getTipo().equals("Identificador")) {
                        tokenaux = proximoToken();
                    }
                    if (tokenaux.getToken().equals(",")) {
                        declaracaoConstantesMesmoTipo(tokenaux);
                    } else if (tokenaux.getToken().equals(";")) {
                        tokenaux = proximoToken();
                        declaracaoConstantes(tokenaux);
                    } else if (tokenaux.getToken().equals("}")) {
                        declaracaoConstantes(tokenaux);
                    } else if (tokenaux.getTipo().equals("Identificador") || tokenaux.getToken().equals("Palavra Reservada")) {
                        System.out.println("Erro ';' esperado e não encontrado");
                        declaracaoConstantes(tokenaux);
                     }

                }
            } else {
                System.out.println("ERRO: Identificador não encontrado");
                while (!tokenaux.getToken().equals(",") && !tokenaux.getToken().equals(";") && !tokenaux.getToken().equals("}")
                        && !tokenaux.getTipo().equals("Identificador")) {
                    tokenaux = proximoToken();
                }
                if (tokenaux.getToken().equals(",")) {
                    declaracaoConstantesMesmoTipo(tokenaux);
                } else if (tokenaux.getToken().equals(";")) {
                    tokenaux = proximoToken();
                    declaracaoConstantes(tokenaux);
                } else if (tokenaux.getToken().equals("}")) {
                    declaracaoConstantes(tokenaux);
                } else if (tokenaux.getTipo().equals("Identificador")) {
                    if (tokenaux.getTipo().equals("Identificador")) {
                        tokenaux = proximoToken();
                        if (tokenaux.getToken().equals("=")) {
                            tokenaux = proximoToken();
                            valorConstante(tokenaux);
                            declaracaoConstantesMesmoTipo(tokenaux);
                        }
                    }
                }

            }
        } else if (tokenaux.getToken().equals(";")) {
            tokenaux = proximoToken();
            declaracaoConstantes(tokenaux);
        }
        else if(tokenaux.getToken().equals(";")){
            tokenaux=proximoToken();
            declaracaoConstantes(tokenaux);
        } else if (tokenaux.getTipo().equals("Identificador") || tokenaux.getTipo().equals("Palavra Reservada")) {
            System.out.println("ERRO: ';' não encontrado");
            declaracaoConstantes(tokenaux);

        }


    }

    public void valorConstante(Token token) {

        if (tokenaux.getTipo().equals("String") || tokenaux.getTipo().equals("Numero Inteiro") || tokenaux.getTipo().equals("CARACTERE BEM FORMADO")
                || tokenaux.getToken().equals("verdadeiro") || tokenaux.getToken().equals("falso")) {
            System.out.println("Valor atribuido com sucesso");
            tokenaux = proximoToken();
        } else {
            System.out.println("ERRO Valor inesperado");
        }

    }

    public void declaracaoConstantes(Token token) {

        tokenaux = token;

        if (tokenaux.getToken().equals("}")) {
            System.out.println("Fim do bloco de constantes declarado");
            tokenaux = proximoToken();
        } else if (tokenaux.getTipo().equals("Palavra Reservada") || tokenaux.getTipo().equals("Identificador")) {
            // System.out.println("Cu");
            tipoConstante(tokenaux);
            if (tokenaux.getTipo().equals("Identificador")) {
                tokenaux = proximoToken();
                if (tokenaux.getToken().equals("=")) {
                    tokenaux = proximoToken();
                    valorConstante(tokenaux);
                    declaracaoConstantesMesmoTipo(tokenaux);
                } else {
                    System.out.println("Operador '=' não encontrado, Valor não encontrado");
                    while (!tokenaux.getToken().equals(",") && !tokenaux.getToken().equals(";")
                            && !tokenaux.getToken().equals("}")) {
                        tokenaux = proximoToken();
                    }
                    if (tokenaux.getToken().equals(",")) {
                        declaracaoConstantesMesmoTipo(tokenaux);
                    } else if (tokenaux.getToken().equals(";")) {
                        tokenaux = proximoToken();
                        declaracaoConstantes(tokenaux);
                    } else if (tokenaux.getToken().equals("}")) {
                        declaracaoConstantes(tokenaux);
                    }

                }
            } else {
                System.out.println("Identificador não em contrado.");
                while (!tokenaux.getToken().equals("}") && !tokenaux.getToken().equals(",") && !tokenaux.getToken().equals(";")
                        && !tokenaux.getTipo().equals("Identificador")) {
                    tokenaux = proximoToken();
                }
                if (tokenaux.getTipo().equals("Identificador")) { //to aki
                    tokenaux = proximoToken();
                    if (tokenaux.getToken().equals("=")) {
                        tokenaux = proximoToken();
                        valorConstante(tokenaux);
                        declaracaoConstantesMesmoTipo(tokenaux);
                    }
                } else if (tokenaux.getToken().equals("}")) {
                    System.out.println("constante não declarada!");
                    declaracaoConstantes(tokenaux);
                } else if (tokenaux.getToken().equals(",")) {
                    declaracaoConstantesMesmoTipo(tokenaux);
                } else if (tokenaux.getToken().equals(";")) {
                    declaracaoConstantesMesmoTipo(tokenaux);
                }
            }

        } else {
            System.out.println("Tipo de constante não encontrado");
            while (!tokenaux.getTipo().equals("Palavra Reservada") && !tokenaux.getTipo().equals("Identificador") && !tokenaux.getTipo().equals("}")) {
                tokenaux = proximoToken();
            }
            if (tokenaux.getTipo().equals("Palavra Reservada") || tokenaux.getTipo().equals("Identificador")) {
                if (tokenaux.getTipo().equals("Identificador")) {
                    tokenaux = proximoToken();
                    if (tokenaux.getToken().equals("=")) {
                        tokenaux = proximoToken();
                        valorConstante(tokenaux);
                        declaracaoConstantesMesmoTipo(tokenaux);
                    }
                }
            } else if (tokenaux.getToken().equals("}")) {
                System.out.println("Fim do bloco de constantes declarado");
                tokenaux = proximoToken();
            }
        }

    }

    public void tipoConstante(Token token) {
        //System.out.println("Entrou no tipo!!!!!" + token.getToken());
        if (token.getToken().equals("inteiro") || token.getToken().equals("real") || token.getToken().equals("cadeia")
                || token.getToken().equals("caractere") || token.getTipo().equals("Identificador") || token.getToken().equals("logico")) {

            System.out.println("Tipo Identificado: " + tokenaux.getToken());
            tokenaux = proximoToken();
        } else {
            System.out.println("Tipo não encontrado!");
            tokenaux = proximoToken();
            declaracaoConstantes(tokenaux);
            while (!token.getToken().equals("inteiro") && !token.getToken().equals("real") && !token.getToken().equals("cadeia")
                    && !token.getToken().equals("caractere") && !token.getTipo().equals("Identificador") && !token.getToken().equals("logico")
                    && token.getToken().equals("}")) {
                tokenaux = proximoToken();
            }
            if (tokenaux.getToken().equals("}")) {
                declaracaoConstantes(tokenaux);
            } else if (tokenaux.getToken().equals("inteiro") || tokenaux.getToken().equals("real") || tokenaux.getToken().equals("cadeia")
                    || tokenaux.getToken().equals("caractere") || tokenaux.getTipo().equals("Identificador") || tokenaux.getToken().equals("logico")) {
                declaracaoConstantes(tokenaux);
            }
        }


    }

    public void tipo(Token token) {
        System.out.println("Entrou no tipo!!!!!" + token.getToken());
        if (token.getToken().equals("inteiro") || token.getToken().equals("real") || token.getToken().equals("cadeia")
                || token.getToken().equals("caractere") || token.getTipo().equals("Identificador") || token.getToken().equals("logico")) {

            System.out.println("Tipo Identificado");
            tokenaux = proximoToken();
        } else {
            System.out.println("Tipo não encontrado!");
        }

    }

     public void tipoFuncao(Token token) {
        System.out.println("Entrou no tipo_funcao!!!!!" + token.getToken());
        if (token.getToken().equals("inteiro") || token.getToken().equals("real") || token.getToken().equals("cadeia")
                || token.getToken().equals("caractere") || token.getTipo().equals("Identificador") || token.getToken().equals("logico") || token.getToken().equals("vazio")) {

            System.out.println("Tipo_Função Identificado");
            tokenaux = proximoToken();
        } else {
            System.out.println("Tipo_Função não encontrado!");
        }

    }
        public void constantes(Token token) {
        tokenaux = token;

        if (tokenaux.getToken().equals("constantes")) {
            tokenaux = proximoToken();
            if (tokenaux.getToken().equals("{")) {
                tokenaux = proximoToken();
                declaracaoConstantes(tokenaux); //terminar a implementação de reconhecimento de constantes
            } else {
                System.out.println("{ Faltando em constantes");
                declaracaoConstantes(tokenaux);
            }
        } else {
            System.out.println("Bloco de constantes não declarado");
            while (!tokenaux.getToken().equals("variaveis") && !tokenaux.getToken().equals("registro") && !tokenaux.getToken().equals("tipo")
                    && !tokenaux.getToken().equals("funcao") && !tokenaux.getToken().equals("principal")) {
                tokenaux = proximoToken();
            }
            if (tokenaux.getToken().equals("variaveis")) {
                System.out.println("encontrou variáveis");
            } else if (tokenaux.getToken().equals("registro")) {
                System.out.println("encontrou registro");
            }
        }

    }


        public void variaveis(){

        }



        public void variaveis(Token token) {
        tokenaux = token;

        if (tokenaux.getToken().equals("variaveis")) {
            System.out.println("Entrou no blobo Variaveis");
            tokenaux = proximoToken();
            if (tokenaux.getToken().equals("{")) {
                System.out.println("{ encontrado");
                tokenaux = proximoToken();
                declaracaoVariaveis(tokenaux);
            } else {
                System.out.println("{ Faltando em variaveis");
                declaracaoVariaveis(tokenaux);
            }
        } else {
            System.out.println("Bloco de variaveis não declarado");
            while (!tokenaux.getToken().equals("registro") && !tokenaux.getToken().equals("tipo")
                    && !tokenaux.getToken().equals("funcao") && !tokenaux.getToken().equals("principal") && !tokenaux.getTipo().equals("Palavra Reservada")) {
                tokenaux = proximoToken();
            }
        }


    }


    public void declaracaoVariaveis(Token token) {
        tokenaux = token;

        if (tokenaux.getTipo().equals("Palavra Reservada") || tokenaux.getTipo().equals("Identificador")) {
            tipo(tokenaux);
            tokenaux = proximoToken();
            if (tokenaux.getTipo().equals("Identificador")) {
                System.out.println("Identificador: "+tokenaux.getToken()+" encontrado.");
                tokenaux = proximoToken();
                declaraVariavelouArray(tokenaux);

            } else {
                System.out.println("Identificador nao encontrado!");
                while (!tokenaux.getToken().equals(",") && !tokenaux.getToken().equals(";")
                        && !tokenaux.getTipo().equals("Identificador")) {
                    tokenaux = proximoToken();
                }
                if (tokenaux.getToken().equals(",")) {
                    tokenaux = proximoToken();
                    declaracaoVariaveis(tokenaux);
                } else if (tokenaux.getToken().equals(";")) {
                    tokenaux = proximoToken();
                 //   System.out.println("Variavel declarada com Sucesso!");
                    declaracaoVariaveis(tokenaux);
                } else if (tokenaux.getTipo().equals("Identificador")) {
                    tokenaux = proximoToken();
                    declaraVariavelouArray(tokenaux);
                }
                else if(tokenaux.getTipo().equals("}")){
                    declaracaoVariaveis(tokenaux);
                }
            }

        } else if(tokenaux.getToken().equals("}")){
            System.out.println("Bloco variaveis fechado.");
        }
        /*while(!tokenaux.getToken().equals("}")&&!tokenaux.getTipo().equals("Palavra Reservada")&&
                !tokenaux.getTipo().equals("Identificador")&&tokenaux.getToken().equals(";")){
            tokenaux=proximoToken();
        }
         if (tokenaux.getToken().equals("}")) {
            System.out.println("Fim do bloco de variáveis");
            tokenaux = proximoToken();
        }
        else if(tokenaux.getToken().equals(";")){
            tokenaux=proximoToken();
            declaracaoVariaveis(tokenaux);
        }
        else if(tokenaux.getToken().equals("registro")||tokenaux.getToken().equals("funcao")||tokenaux.getToken().equals("constantes")
                ||tokenaux.getToken().equals("principal")){
             System.out.println("} não encontrado!");
        }*/



    }

    public void declaraVariavelouArray(Token token) {
        tokenaux = token;
        if (tokenaux.getToken().equals("=")) {
            inicializaVariavel(tokenaux);
        } else if (tokenaux.getToken().equals("[")) {
            array(tokenaux);
        }else{
            System.out.println("Operador '=' não encontrado, ou '[' faltando na declaração do vetor");
            while(!tokenaux.getToken().equals(",")&&!tokenaux.getToken().equals(";")&&
                    !tokenaux.getTipo().equals("Identificador")){

            }
            if(tokenaux.getToken().equals(",")){
                 declaracaoVariavelMesmoTipo(token);//parei aqui!!!
             }
        }


    }

    public void inicializaVariavel(Token token) {
        tokenaux = token;
        if (tokenaux.getToken().equals("=")) {
            System.out.println("Operador = reconhecido.");
            tokenaux=proximoToken();
            valorVariavel(tokenaux);
            declaracaoVariavelMesmoTipo(token);
        } else if (tokenaux.getToken().equals(",")) {
            declaracaoVariavelMesmoTipo(tokenaux);
        }
        else{
            System.out.println("ERRO: operador '=' faltando, ou ',' não presente em "+tokenaux.getToken());
        }
    }

    public void declaracaoVariavelMesmoTipo(Token token) {

        if (tokenaux.getToken().equals(",")) {
            tokenaux = proximoToken();
            if (tokenaux.getTipo().equals("Identificador")) {
                System.out.println("Identificador: "+tokenaux.getToken()+" encontrado.");
                tokenaux = proximoToken();
                inicializaVariavel(tokenaux);
            }
        } else if (tokenaux.getToken().equals(";")) {
            System.out.println("Fim da declaração de variavel");
            tokenaux = proximoToken();
            declaracaoVariaveis(tokenaux);
        }

    }

    public void valorVariavel(Token token) {
        tokenaux = token;
        if (tokenaux.getTipo().equals("cadeia") || tokenaux.getTipo().equals("Numero Inteiro") || tokenaux.getTipo().equals("Numero Real")
                || tokenaux.getTipo().equals("caractere") || tokenaux.getTipo().equals("logico")) {
            System.out.println("Valor: "+tokenaux.getToken()+" atribuido!!");
            tokenaux = proximoToken();
        } else {
            System.out.println("Valor não encontrado!");
        }
    }

    public void array(Token token) {
        tokenaux = token;

        if (tokenaux.getToken().equals("[")) {
            tokenaux = proximoToken();
            if (tokenaux.getTipo().equals("Numero Inteiro")) {
                tokenaux = proximoToken();
                if (tokenaux.getToken().equals("]")) {
                    System.out.println("Declaração do vetor realizada com sucesso.");
                    tokenaux = proximoToken();
                    declaracaoVetorouMatriz(tokenaux);
                }
            }
        }
    }

    public void declaracaoVetorouMatriz(Token token) {
        tokenaux = token;
        if (tokenaux.getToken().equals("[")) {
            tokenaux = proximoToken();
            if (tokenaux.getTipo().equals("Numero Inteiro")) {
                tokenaux = proximoToken();
                if (tokenaux.getToken().equals("]")) {
                    System.out.println("Matriz declarada com sucesso!");
                    tokenaux = proximoToken();
                    declaracaoMatrizMesmoTipo(tokenaux);
                }
            }
        } else if (tokenaux.getToken().equals(",")) {
            declaraVetorMesmoTipo(tokenaux);
        }
        else if(tokenaux.getToken().equals(";")){
            declaracaoVariaveis(tokenaux);
        }
    }

    public void declaracaoMatrizMesmoTipo(Token token) {
        tokenaux = token;
        if (tokenaux.getToken().equals(",")) {
            tokenaux = proximoToken();
            if (tokenaux.getTipo().equals("Identificador")) {
                tokenaux = proximoToken();
                if (tokenaux.getToken().equals("[")) {
                    tokenaux = proximoToken();
                    if (tokenaux.getTipo().equals("Numero Inteiro")) {
                        tokenaux = proximoToken();
                        if (tokenaux.getToken().equals("]")) {
                            tokenaux = proximoToken();
                            if (tokenaux.getToken().equals("[")) {
                                tokenaux = proximoToken();
                                if (tokenaux.getTipo().equals("Numero Inteiro")) {
                                    tokenaux = proximoToken();
                                    if (tokenaux.getToken().equals("]")) {
                                        tokenaux = proximoToken();
                                        System.out.println("Matriz declarada com sucesso.");
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        else if (tokenaux.getToken().equals(";")){
            System.out.println("Fim da declaração Matriz!");
            declaracaoVariaveis(tokenaux);
        }

    }

    public void declaraVetorMesmoTipo(Token token) {
        tokenaux = token;
        if (tokenaux.getToken().equals(",")) {
            tokenaux = proximoToken();
            if (tokenaux.getTipo().equals("Identificador")) {
                tokenaux = proximoToken();
                if (tokenaux.getToken().equals("[")) {
                    tokenaux = proximoToken();
                    if (tokenaux.getTipo().equals("Numero Inteiro")) {
                        tokenaux = proximoToken();
                        if (tokenaux.getToken().equals("]")) {
                            tokenaux = proximoToken();
                            System.out.println("Vetor declarado com sucesso.");
                            declaracaoVariavelMesmoTipo(tokenaux);
                        }
                    }
                }
            }
        } else if (tokenaux.getToken().equals(";")) {
            declaracaoVariaveis(tokenaux);
        }

    }







    public void inicio(Token token) {

        System.out.println("entrou");
        if (token.getToken().equals("programa") || noprograma == 1) {
            if (noprograma != 1) {
                System.out.println("programa econtrado");
                if (noidentificador == 0) {
                    tokenaux = proximoToken();
                } else {
                    tokenaux = token;
                }
            } else {
                tokenaux = token;
            }

            if (tokenaux.getTipo().equals("Identificador") || noidentificador == 1) {
                if (noidentificador != 1) {
                    System.out.println("identificador encontrado");
                    tokenaux = proximoToken();
                } else {
                    tokenaux = token;
                }
                if (tokenaux.getToken().equals(";")) {
                    System.out.println("';' encontrado");
                    estrutura(proximoToken());
                } else {
                    System.out.println("ERRO:  Esperado o ';' ");
                    for (int i = indiceToken; i < listadeTokens.size(); i++) {

                        if (tokenaux.getToken().equals(";")) {
                            System.out.println("';' encontrado");
                            break;
                        } else if (tokenaux.getTipo().equals("Palavra Reservada")) {
                            System.out.println("';' esperado, mas encontrado Palavra Reservada");
                            break;
                        }
                        tokenaux = proximoToken();
                    }
                    estrutura(tokenaux);
                }
            } else {
                System.out.println("ERRO: Identificador não encontrado");
                noidentificador = 1;
                inicio(tokenaux);
            }
        } else {
            if (noidentificador == 0) {
                System.out.println("ERRO: 'Programa' não encontrado");
            }
            noprograma = 1;
            inicio(token);
        }


    }

    public void analyseListTokens() {

        inicio(proximoToken());
        if (tokenaux.getToken().equals("$")) {
            System.out.println("SUCESSO");
            System.exit(0);
        } else if (proximoToken().getToken().equals("$")) {
            System.out.println("SUCESSO");
            System.exit(0);
        }

    }

    public Token proximoToken() {
        if (listadeTokens.size() > indiceToken) {
            Token token = listadeTokens.get(indiceToken);
            indiceToken++;
            return token;
        } else {
            System.out.println("Fim dos tokens");

            JOptionPane.showMessageDialog(null, "Fim dos tokens");
            System.exit(0);


            return null;
        }


    }

    public void imprimeListaToken() {

        for (int i = 0; i < listadeTokens.size(); i++) {

            System.out.println("" + listadeTokens.get(i).getToken() + "\n");
        }

    }
}
